home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1994 October / macformat-005.iso / Shareware City / Developers / GENetRelease2ƒ / GETest / SynchTest.c < prev   
Encoding:
C/C++ Source or Header  |  1994-06-24  |  21.1 KB  |  935 lines  |  [TEXT/MPS ]

  1. /*
  2.     SynchTest.c
  3.     
  4.     Test program for exploring relationship between number of objects, object move,
  5.     object update interval, and frame update interval
  6.     
  7.     1/29/94
  8.     
  9.     Al Evans
  10. */
  11.  
  12. #ifdef applec
  13. #ifndef PRELOAD
  14. #pragma load "::ToolKit.precompile"
  15. #define PRELOAD
  16. #endif
  17. #else
  18. #include <QDOffscreen.h>
  19. #endif
  20.  
  21. #include <Timer.h>
  22. #include <GestaltEqu.h>
  23.  
  24. #include "GUtilities.h"
  25. #include "GrowWindConst.h"
  26. #include "GraphElements.h"
  27. #include "GridElement.h"
  28. #include "SynchGraphic.h"
  29. #include "Meter.h"
  30. #include "GELogo.h"
  31.  
  32. //define HISTOGRAM to collect times history
  33. #undef HISTOGRAM
  34.  
  35. #ifdef HISTOGRAM
  36. #include "StdIO.h"
  37. #endif
  38.  
  39. //define PERFORMANCE to collect profiling data for MPW
  40. #undef PERFORMANCE
  41. #ifdef PERFORMANCE
  42. #include <Perf.h>
  43. #endif
  44.  
  45. //define DOPROFILE for Think C profiler
  46. #undef DOPROFILE
  47.  
  48. #ifdef THINK_C
  49. #ifdef DOPROFILE
  50. #include <StdIO.h>
  51. #include <Profile.h>
  52. #endif
  53. #endif
  54.  
  55.  
  56. //Menu Commands
  57.  
  58. #define    rMenuBar                128        /* application's menu bar */
  59.  
  60. #define    mApple                    128        /* Apple menu */
  61. #define    iAbout                    1
  62.  
  63. #define    mFile                    129        /* File menu */
  64. #define    iQuit                    1
  65.  
  66. #define    mEdit                    130        /* Edit menu */
  67. #define    iUndo                    1
  68. #define    iCut                    3
  69. #define    iCopy                    4
  70. #define    iPaste                    5
  71. #define    iClear                    6
  72.  
  73. #define mSpecial                131
  74. #define iSetParams                1
  75. #define iMeter                    2
  76. #define iTiming                    3
  77. #define iSingleFrame            4
  78.  
  79. #define    rAboutDialog    228        
  80. #define rUserAlert        129
  81. #define rPerfAlert        300
  82. #define rSetParamsDialog    135
  83.  
  84. //Resource numbers of graphic PICTs
  85. #define    rBkgPic 200
  86.  
  87. //Number of master pointer blocks needed
  88.  
  89. #define masterBlocksNeeded 10
  90.  
  91. //Globals
  92.  
  93. #ifdef PERFORMANCE
  94. TP2PerfGlobals        thePGlobals;
  95. #endif
  96.  
  97. Boolean        gFinished;
  98. WindowPtr    gAnimWindow;
  99. Boolean        gSingleFrame = false;
  100. Boolean        gDoOne = false;
  101. Boolean        gMeterShown = true;
  102. Rect        gWorldBaseRect;
  103. Rect        gWorldLimRect;
  104.  
  105. //Performance measurement
  106.  
  107. #define thirtySeconds 30L * 1000 * 1000        //µsec for timers -- never time out
  108.  
  109. TMTask    gTTimeTask, gATimeTask;
  110. unsigned long gTotalTime = 0, gAnimTime = 0;
  111.  
  112. #ifdef HISTOGRAM
  113. long    autoChgTimes[100];
  114. long    postChgTimes[100];
  115. long    udOffScrTimes[100];
  116. long    copyTimes[100];
  117. long    totalTimes[100];
  118. #endif
  119.  
  120. //QD Globals for PowerPC
  121. #if    __ppcc
  122. QDGlobals     qd;
  123. #endif
  124.  
  125. //Forward declarations
  126.  
  127. #ifdef applec
  128. extern void _DataInit();    //reference so that we can unload it
  129. #endif
  130.  
  131. Boolean Initialize( void );
  132. void Shutdown(void);
  133. void EventLoop( void );
  134.  
  135. main()
  136. {
  137. #ifdef applec
  138.     UnloadSeg((Ptr) _DataInit);
  139. #endif
  140. #ifdef THINK_C
  141. #ifdef DOPROFILE
  142.     InitProfile(200,200);
  143.     freopen("TCProfile.out", "w", stdout);
  144. #endif
  145. #endif
  146.     
  147.     MaxApplZone();
  148.     if ( Initialize() )
  149.         EventLoop();
  150. #ifdef THINK_C
  151. #ifdef DOPROFILE
  152.     DumpProfile();
  153. //    fflush(stdout);
  154. //    fclose(stdout);
  155. #endif
  156. #endif
  157.     Shutdown();
  158. }
  159.  
  160.  
  161. //Initialization
  162.  
  163. Boolean AdequateSystem(void)
  164. {
  165.     OSErr        err;
  166.     long        response;
  167.     Boolean        ok;
  168.     
  169.     //We need 68020 or better
  170.     err = Gestalt(gestaltProcessorType, &response);
  171.     ok = (!err) & (response >= gestalt68020);
  172.     
  173.     //We need System 7 or later
  174.     err = Gestalt(gestaltSystemVersion, &response);
  175.     ok = (!err) & (((response & 0xFFFF) / 256) >= 7);
  176.     
  177.     //We need color QD & offscreen GWorlds
  178.     err = Gestalt(gestaltQuickdrawVersion, &response);
  179.     ok = ok & (!err) & (response >= gestalt32BitQD);
  180.     err = Gestalt(gestaltQuickdrawFeatures, &response);
  181.     ok = ok & (!err) & (response >= 3);         //hasColor & deep GWorlds
  182.     
  183.     return ok;
  184.     
  185. }
  186.  
  187. //Make window centered on main graphic device
  188. WindowPtr MakeWindow(short wHSize, short wVSize)
  189. {
  190.     GDHandle    mainDevice;
  191.     Rect        devRect;
  192.     short        hOffst, vOffst;
  193.     Rect        windRect;
  194.     
  195.     mainDevice = GetMainDevice();
  196.     devRect = (**mainDevice).gdRect;
  197.     gWorldLimRect.top = wVSize / 2;
  198.     gWorldLimRect.left = wHSize / 2;
  199.     gWorldLimRect.bottom = RectHeight(&devRect);
  200.     gWorldLimRect.right = RectWidth(&devRect);
  201.     hOffst = (devRect.right - devRect.left - wHSize) / 2;
  202.     if (hOffst < 0) hOffst = 0;
  203.     vOffst = (devRect.bottom - devRect.top - wVSize) / 2;
  204.     if (vOffst < 0 ) vOffst = 0;
  205.     windRect.left = hOffst;
  206.     windRect.right = hOffst + wHSize;
  207.     windRect.top = vOffst;
  208.     windRect.bottom = vOffst + wVSize; 
  209.     
  210.     return NewCWindow(nil, &windRect, "\pSynch Test", false, documentProc,
  211.                         (WindowPtr) -1L, false, 0L);
  212. }
  213.  
  214.  
  215. void InitPerformanceTiming(void)
  216. {
  217.     //Init Timers
  218.     gTTimeTask.tmAddr = nil;
  219.     gTTimeTask.tmWakeUp = 0;
  220.     gTTimeTask.tmReserved = 0;
  221.     
  222.     gATimeTask.tmAddr =  nil;
  223.     gATimeTask.tmWakeUp = 0;
  224.     gATimeTask.tmReserved = 0;
  225.     
  226. }
  227.  
  228. Boolean LoadBackground(GEWorldPtr world)
  229. {
  230.     GrafElPtr    bkg;
  231.     //if (bkg = NewBasicPICT(world, 'BKG ', 1, rBkgPic, srcCopy, 0, 0))
  232.     if (bkg = NewGridPICT(world, 'BKG ', 1, rBkgPic, srcCopy, 0, 0, 128, 128))
  233.         return true;
  234.     return false;
  235. }
  236.  
  237. Boolean AddGrowBox(GEWorldPtr world)
  238. {
  239.     GrafElPtr    growBox;
  240.     
  241.     growBox = NewBasicPICT(world, 'GBOX', 32100, 20000, srcCopy, 
  242.                         gWorldBaseRect.right - 15, gWorldBaseRect.bottom - 15);
  243.     return (growBox != nil);
  244. }
  245.  
  246. Boolean InitializeGEWorld(WindowPtr window, Rect * refRect, Rect *actRect)
  247. {
  248.     Fixed        propH, propV;
  249.     Fixed        worldScale;
  250.     GEWorldPtr    animWorld;
  251.     
  252.     propH = (RectWidth(actRect) * 65536) / RectWidth(refRect);
  253.     propV = (RectHeight(actRect) * 65536) / RectHeight(refRect);
  254.     worldScale = (propH > propV?propH:propV);
  255.     
  256.     animWorld = NewGEWorld(window, refRect, worldScale , nil);
  257.     if (animWorld == nil) {
  258.         TellUser("\pCould not create new GEWorld.", 0);
  259.         return false;
  260.     }
  261.     if (!LoadBackground(animWorld)) {
  262.         TellUser("\pCould not load background", 0);
  263.         return false;
  264.     }
  265.     if (!InitObjectGraphics(animWorld)) {
  266.         TellUser("\pCould not load test graphic", 0);
  267.         return false;
  268.     }
  269.  
  270.     if (!LoadUsageMeterScene(animWorld)) {
  271.         TellUser("\pCould not load usage meter", 0);
  272.         return false;
  273.     }
  274.     if (!LoadLogoScene(animWorld)) {
  275.         TellUser("\pCould not load GE logo", 0);
  276.         return false;
  277.     }
  278.     if (!AddGrowBox(animWorld)) {
  279.         TellUser("\pCould not add grow box", 0);
  280.         return false;
  281.     }
  282.     //Reposition meter a little to the left
  283.     MoveElement(animWorld, meterBkgID, -100, 0);
  284.     SetWRefCon(gAnimWindow, (long) animWorld);
  285.     return true;
  286. }
  287.  
  288. //Tacky import from SynchGraphic
  289. extern Ptr objMask;
  290. void ChangeWorldSize(WindowPtr window, short newWidth, short newHeight)
  291. {
  292.     Rect    animRect;
  293.     
  294.     //Save window setup
  295.     long        oNumObj = GetNumberOfObjects();
  296.     long        oMoveDist = GetMoveDistance();
  297.     long        oSep = GetObjSeparation();
  298.     long        oObjUpdate = GetUpdateInterval();
  299.     Boolean        oMovement = MotionIsLinear();
  300.     Boolean        collision = ObjCollisionActive();
  301.     
  302.     DisposeGEWorld((GEWorldPtr) GetWRefCon(window));
  303.     DisposPtr(objMask);
  304.     SetRect(&animRect, 0, 0, newWidth, newHeight);
  305.     if (!InitializeGEWorld(window, &gWorldBaseRect, &animRect)) {
  306.         TellUser("\pCould not resize animated world.", 0);
  307.         ExitToShell();
  308.     }
  309.     //Restore window setup
  310.     SetMoveDistance((GEWorldPtr) GetWRefCon(window), oMoveDist);
  311.     SetObjSeparation((GEWorldPtr) GetWRefCon(window), oSep);
  312.     SetUpdateInterval((GEWorldPtr) GetWRefCon(window), oObjUpdate);
  313.     SetObjMotionLinear(oMovement);
  314.     SetNumberOfObjects((GEWorldPtr) GetWRefCon(window), oNumObj);
  315.     SetObjCollision((GEWorldPtr) GetWRefCon(window), collision);
  316.     ActivateWorld((GEWorldPtr) GetWRefCon(window), true);
  317.  
  318. }
  319.  
  320. Boolean Initialize(void)
  321. {
  322.     Rect        animRect;
  323.     GEWorldPtr    animWorld;
  324. #ifdef HISTOGRAM
  325.     short    count;
  326. #endif
  327.     
  328.     gFinished = false;
  329.     
  330.     InitSystem(masterBlocksNeeded);
  331.     
  332.     
  333.     if (!AdequateSystem()) {
  334.         TellUser("\pSorry, more powerful system required", 0);
  335.         return false;
  336.     }
  337.     if (!LoadMenus(rMenuBar)) {
  338.         TellUser("\pCould not load menus", 0);
  339.         return false;
  340.     }
  341.     
  342.     gAnimWindow = MakeWindow(512, 364);
  343.     if (gAnimWindow == nil) {
  344.         TellUser("\pCould not create window", 0);
  345.         return false;
  346.     }
  347.     SetRect(&gWorldBaseRect, 0, 0, 512, 364);
  348.     animRect = gWorldBaseRect;
  349.     if (!InitializeGEWorld(gAnimWindow, &gWorldBaseRect, &animRect)) {
  350.         TellUser("\pCould not create animated world.", 0);
  351.         return false;
  352.     }
  353.     
  354.     InitPerformanceTiming();
  355.     
  356. #ifdef HISTOGRAM
  357.     for (count = 0; count < 100; count++) {
  358.         autoChgTimes[count] = 0;
  359.         postChgTimes[count] = 0;
  360.         udOffScrTimes[count] = 0;
  361.         copyTimes[count] = 0;
  362.         totalTimes[count] = 0;
  363.     }
  364. #endif
  365.     
  366. #ifdef PERFORMANCE
  367.     thePGlobals = nil;
  368.     if (!InitPerf( &thePGlobals, 10, 8, true, true, "\pCODE", 0, "\p", false, 0L, 0L, 0) ){
  369.         TellUser("\pCould not initialize profiling", 0);
  370.         return false;
  371.     }
  372. #endif
  373.     
  374.     //Turn animation on and show window
  375.     SetObjMotionLinear(false);
  376.     SetNumberOfObjects((GEWorldPtr) GetWRefCon(gAnimWindow), 4);
  377.     SetObjCollision((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  378. #if FORPPC
  379.         TellUser("\pGoing to activate world", 0);
  380. #endif
  381.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  382. #if FORPPC
  383.         TellUser("\pGoing to show window", 0);
  384. #endif
  385.     ShowWindow(gAnimWindow);
  386.     
  387. }
  388.  
  389. #ifdef HISTOGRAM
  390. void DumpHistograms(void)
  391. {
  392.     short    count;
  393.     FILE*    dump;
  394.     
  395.     dump = fopen("HistoDump", "w");
  396.     for (count = 0; count < 100; count++) 
  397.         fprintf(dump, "%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", count, autoChgTimes[count], 
  398.             postChgTimes[count], udOffScrTimes[count], copyTimes[count], totalTimes[count]);
  399.     fflush(dump);
  400.     fclose(dump);
  401. }
  402. #endif
  403.  
  404. void Shutdown(void)
  405. {
  406. #ifdef PERFORMANCE
  407.     OSErr err;
  408. #endif
  409.     //Release system resources
  410.     
  411. #ifdef HISTOGRAM
  412.     DumpHistograms();
  413. #endif
  414. #ifdef PERFORMANCE
  415.     err = PerfDump(thePGlobals, "\pPerform.out", false, 0);
  416. #endif
  417.     StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  418.     ExitToShell();
  419. }
  420.  
  421. #ifdef HISTOGRAM
  422.  
  423. void RunHistogram(void)
  424. {
  425.     
  426.     if (gAutoChgTime < 100)
  427.         autoChgTimes[gAutoChgTime]++;
  428.     else
  429.         autoChgTimes[100]++;
  430.         
  431.     if (gPostChgTime < 100)
  432.         postChgTimes[gPostChgTime]++;
  433.     else
  434.         postChgTimes[100]++;
  435.         
  436.     if (gUDOffScrTime < 100)
  437.         udOffScrTimes[gUDOffScrTime]++;
  438.     else
  439.         udOffScrTimes[100]++;
  440.         
  441.     if (gCopyTime < 100)
  442.         copyTimes[gCopyTime]++;
  443.     else
  444.         copyTimes[100]++;
  445.         
  446.     if (gTtlLoopTime < 100)
  447.         totalTimes[gTtlLoopTime]++;
  448.     else
  449.         totalTimes[100]++;
  450.         
  451. }    
  452.  
  453. #else
  454.  
  455. void RunHistogram(void)
  456. {
  457.     
  458. }
  459. #endif
  460.  
  461. void RunMeterAnimation(short ms)
  462. {
  463.     static short    setting = 0;
  464.     
  465.     if (gMeterShown && (ms > 1)) {
  466.         if (ms == setting)
  467.             return;
  468.         if (ms > setting)
  469.             setting++;
  470.         else
  471.             if (ms < setting)
  472.                 setting--;
  473.         SetMeterReading((GEWorldPtr) GetWRefCon(gAnimWindow), 2 * setting);
  474.     }
  475.     
  476. }
  477.  
  478. void DisplayPerformance(long frames, long seconds)
  479. {
  480.     Str255 framesString, secondsString, fpsString;
  481.     long fps;
  482.     
  483.     NumToString(frames, framesString);
  484.     NumToString(seconds, secondsString);
  485.  
  486.     fps = (seconds > 0) ? frames / seconds : frames;
  487.     NumToString(fps, fpsString);
  488.  
  489.     ParamText(framesString, secondsString, fpsString, "\p");
  490.     NoteAlert(rPerfAlert, nil);
  491. }
  492.  
  493. void DoTimingLoop(void)
  494. {
  495.     long ticks;
  496.     short oObjUpdate;
  497.     unsigned long frames, seconds;
  498.     GEWorldPtr    world = (GEWorldPtr) GetWRefCon(gAnimWindow);
  499.     
  500.     oObjUpdate = GetUpdateInterval();
  501.     SetUpdateInterval(world, 1);
  502.     StartGETimer(world);
  503.     ticks = TickCount();
  504.  
  505.     for (frames = 0; ((TickCount() - ticks) < (30 * 60)) && (!Button()); frames++) { 
  506.         DoWorldUpdate(world, false);
  507.     }
  508.     
  509.     seconds = ((TickCount() - ticks) / 60);
  510.     
  511.     DisplayPerformance(frames, seconds);
  512.     //SetUpdateInterval(world, oPIntrvl);
  513.     SetUpdateInterval(world, oObjUpdate);
  514.     
  515. }
  516.  
  517. //Dialog items
  518. #define    dItmNObj    4
  519. #define dItmMDist    6
  520. #define dItmSep        8
  521. #define dItmUpd        10
  522. #define dItmLinear    11
  523. #define dItmRandom    12
  524. #define dItmCollide    13
  525.  
  526. void DoSetParams( void )
  527. {
  528.  
  529.     DialogPtr     frDialog;
  530.     short        itemType;
  531.     Handle        item;
  532.     Rect        okRect;
  533.     Rect        itemRect;
  534.     short        itemHit;
  535.     Str255        tempStr;
  536.     ControlHandle    btnRandom, btnLinear, boxCollide;
  537.     
  538.     long        oNumObj, nNumObj;
  539.     long        oMoveDist, nMoveDist;
  540.     long        oSep, nSep;
  541.     long        oObjUpdate, nObjUpdate;
  542.     Boolean        oMovement, nMovement;    //linear (true) or random
  543.     Boolean        collision;                //if random motion, true == collision enabled
  544.     
  545.     frDialog = GetNewDialog(rSetParamsDialog, nil, (WindowPtr) -1L);
  546.     GetDItem(frDialog, ok, &itemType, &item, &okRect);
  547.     
  548.     //Present number of objects -> dialog
  549.     oNumObj = GetNumberOfObjects();
  550.     GetDItem(frDialog, dItmNObj, &itemType, &item, &itemRect);
  551.     NumToString(oNumObj, tempStr);
  552.     SetIText(item, tempStr);
  553.     
  554.     //Present move distance -> dialog
  555.     oMoveDist = GetMoveDistance();
  556.     GetDItem(frDialog, dItmMDist, &itemType, &item, &itemRect);
  557.     NumToString(oMoveDist, tempStr);
  558.     SetIText(item, tempStr);
  559.     
  560.     //Present object separation -> dialog
  561.     oSep = GetObjSeparation();
  562.     GetDItem(frDialog, dItmSep, &itemType, &item, &itemRect);
  563.     NumToString(oSep, tempStr);
  564.     SetIText(item, tempStr);
  565.     
  566.     //Present object update interval -> dialog
  567.     oObjUpdate = GetUpdateInterval();
  568.     GetDItem(frDialog, dItmUpd, &itemType, &item, &itemRect);
  569.     NumToString(oObjUpdate, tempStr);
  570.     SetIText(item, tempStr);
  571.     
  572.     //Get radio buttons, present object motion -> dialog
  573.     oMovement = MotionIsLinear();
  574.     nMovement = oMovement;
  575.     GetDItem(frDialog, dItmLinear,  &itemType, (Handle *) &btnLinear, &itemRect);
  576.     GetDItem(frDialog, dItmRandom,  &itemType, (Handle *) &btnRandom, &itemRect);
  577.     GetDItem(frDialog, dItmCollide, &itemType, (Handle *) &boxCollide, &itemRect);
  578.     SetCtlValue(btnLinear, oMovement?1:0);
  579.     SetCtlValue(btnRandom, oMovement?0:1);
  580.     collision = ObjCollisionActive();
  581.     HiliteControl(boxCollide, oMovement?255:0);
  582.     SetCtlValue(boxCollide, collision?1:0);
  583.     
  584.     //Do OK button
  585.     InsetRect(&okRect, -4, -4);
  586.     ShowWindow(frDialog);
  587.     SetPort( (GrafPtr) frDialog);
  588.     PenSize(3, 3);
  589.     FrameRoundRect(&okRect, 16, 16);
  590.     
  591.     SelIText(frDialog, dItmNObj, 0, 32767);
  592.     do {
  593.         ModalDialog(nil, &itemHit);
  594.         switch (itemHit) {
  595.             case dItmLinear:
  596.                 nMovement = true;
  597.                 SetCtlValue(btnLinear, 1);
  598.                 SetCtlValue(btnRandom, 0);
  599.                 HiliteControl(boxCollide, 255);
  600.                 break;
  601.             case dItmRandom:
  602.                 nMovement = false;
  603.                 SetCtlValue(btnLinear, 0);
  604.                 SetCtlValue(btnRandom, 1);
  605.                 HiliteControl(boxCollide, 0);
  606.                 break;
  607.             case dItmCollide:
  608.                 SetCtlValue(boxCollide, (GetCtlValue(boxCollide) ==1)?0:1);
  609.                 break;
  610.         }
  611.     } while ( (itemHit != ok) && (itemHit != cancel) );
  612.     
  613.     if (itemHit == ok) {
  614.         //Get new values
  615.         GetDItem(frDialog, dItmNObj, &itemType, &item, &itemRect);
  616.         GetIText(item, tempStr);
  617.         StringToNum(tempStr, &nNumObj);
  618.         GetDItem(frDialog, dItmMDist, &itemType, &item, &itemRect);
  619.         GetIText(item, tempStr);
  620.         StringToNum(tempStr, &nMoveDist);
  621.         GetDItem(frDialog, dItmSep, &itemType, &item, &itemRect);
  622.         GetIText(item, tempStr);
  623.         StringToNum(tempStr, &nSep);
  624.         GetDItem(frDialog, dItmUpd, &itemType, &item, &itemRect);
  625.         GetIText(item, tempStr);
  626.         StringToNum(tempStr, &nObjUpdate);
  627.         if (nMoveDist != oMoveDist)
  628.             SetMoveDistance((GEWorldPtr) GetWRefCon(gAnimWindow), nMoveDist);
  629.         if (nSep != oSep)
  630.             SetObjSeparation((GEWorldPtr) GetWRefCon(gAnimWindow), nSep);
  631.         if (nObjUpdate != oObjUpdate)
  632.             SetUpdateInterval((GEWorldPtr) GetWRefCon(gAnimWindow), nObjUpdate);
  633.         if (oMovement != nMovement)
  634.             SetObjMotionLinear(nMovement);
  635.         if ((nNumObj != oNumObj) || (nSep != oSep) || (oMovement != nMovement))
  636.             SetNumberOfObjects((GEWorldPtr) GetWRefCon(gAnimWindow), nNumObj);
  637.         if (!nMovement) {
  638.             collision = (GetCtlValue(boxCollide) == 1)?true:false;
  639.             SetObjCollision((GEWorldPtr) GetWRefCon(gAnimWindow), collision);
  640.         }
  641.     }
  642.     DisposDialog(frDialog);
  643. }
  644.  
  645. pascal Boolean AboutFilter(DialogPtr dialog, EventRecord *event, short *item)
  646. {
  647. #pragma unused (dialog)
  648.     DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  649.     if ((event->what == mouseDown) || (event->what == keyDown)) {
  650.         *item = ok;
  651.         return true;
  652.     }
  653.     else return false;
  654. }
  655.  
  656. void DoAboutBox(void)
  657. {
  658.     DialogPtr    aboutDialog;
  659.     short        itemHit;
  660. #if NEWHEADERS
  661.     ModalFilterUPP    aboutFilterPtr = NewModalFilterProc(AboutFilter);
  662. #else
  663.     ModalFilterProcPtr        aboutFilterPtr = AboutFilter;
  664. #endif
  665.     
  666.     aboutDialog = GetNewDialog(rAboutDialog, nil, (WindowPtr) -1L);
  667.     ModalDialog(aboutFilterPtr, &itemHit);
  668.     DisposDialog(aboutDialog);
  669. #if FORPPC
  670.     DisposeRoutineDescriptor(aboutFilterPtr);
  671. #endif    
  672. }
  673.  
  674. //Event Handling
  675.  
  676. void EventLoop( void )
  677. {
  678.     Boolean        gotEvent;
  679.     EventRecord    event;
  680.     
  681.     void DoEvent (EventRecord *event);
  682.     void AdjustCursor( void);
  683.     
  684.     do {
  685.         InsTime( (QElemPtr) &gTTimeTask);
  686.         InsTime( (QElemPtr) &gATimeTask);
  687.         PrimeTime( (QElemPtr) &gTTimeTask, -thirtySeconds);
  688.         if (!gSingleFrame || gDoOne) {
  689.             PrimeTime( (QElemPtr) &gATimeTask, -thirtySeconds);
  690.             
  691. #ifdef PERFORMANCE
  692.             (void) PerfControl(thePGlobals, true);
  693. #endif
  694.  
  695.             DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  696.             
  697. #ifdef PERFORMANCE
  698.             (void) PerfControl(thePGlobals, false);
  699. #endif
  700.             RmvTime( (QElemPtr) &gATimeTask);
  701.             gAnimTime = (thirtySeconds + gATimeTask.tmCount) / 1000;
  702.             gDoOne = false;
  703.         }
  704.         AdjustCursor();
  705.         if (gotEvent = WaitNextEvent(everyEvent, &event, 0L, nil)) 
  706.             DoEvent(&event);
  707.         RmvTime( (QElemPtr) &gTTimeTask);
  708.         gTotalTime = (thirtySeconds + gTTimeTask.tmCount) / 1000; //milliseconds
  709.         RunHistogram();
  710.         RunMeterAnimation(gAnimTime);
  711.         
  712.     } while (!gFinished);
  713. }
  714.  
  715. void DoEvent (EventRecord *event)
  716. {
  717.     short        part;
  718.     WindowPtr    window;
  719.     char        key;
  720.     long        newWSize;
  721.     
  722.     //Prototypes
  723.     void AdjustMenus( void );
  724.     void DoMenuCommand(long menuResult);
  725.     void DoActivate(WindowPtr window, Boolean becomingActive);
  726.     void DoUpdate(WindowPtr window);
  727.     
  728.     switch ( event->what ) {
  729.         case mouseDown:
  730.             part = FindWindow(event->where, &window);
  731.             switch ( part ) {
  732.                 case inMenuBar:
  733.                     StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  734.                     AdjustMenus();
  735.                     DoMenuCommand(MenuSelect(event->where));
  736.                     StartGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  737.                     break;
  738.                 case inSysWindow:
  739.                     SystemClick(event, window);
  740.                     break;
  741.                 case inContent:
  742.                     if ( window != FrontWindow() ) 
  743.                         SelectWindow(window);
  744.                     if (MouseDownInSensor((GEWorldPtr) GetWRefCon(gAnimWindow), event->where))
  745.                         ;;
  746.                     break;
  747.                 case inDrag:
  748.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  749.                     break;
  750.                 case inGrow:
  751.                     newWSize = GrowWindowConstrained(window, event->where, 
  752.                                             &gWorldLimRect, &gWorldBaseRect);
  753.                     SizeWindow(window, LoWord(newWSize), HiWord(newWSize), true);
  754.                     ChangeWorldSize(window, LoWord(newWSize), HiWord(newWSize));
  755.                     InvalRect(&((GrafPtr)window)->portRect);
  756.                     break;
  757.  
  758.             }
  759.             break;
  760.         case keyDown:
  761.             key = event->message & charCodeMask;
  762.             if ( event->modifiers & cmdKey ) {
  763.                 StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  764.                 AdjustMenus();
  765.                 DoMenuCommand(MenuKey(key));
  766.                 StartGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  767.             }
  768.             else {
  769.                 switch (key) {
  770.                     case 'U':
  771.                     case 'u':
  772.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, -50);
  773.                         break;
  774.                     case 'D':
  775.                     case 'd':
  776.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, 50);
  777.                         break;
  778.                     case 'R':
  779.                     case 'r':
  780.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 50, 0);
  781.                         break;
  782.                     case 'L':
  783.                     case 'l':
  784.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), -50, 0);
  785.                         break;
  786.                 }
  787.             }
  788.             gDoOne = true;
  789.             break;
  790.         case activateEvt:
  791.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  792.             break;
  793.         case updateEvt:
  794.             DoUpdate((WindowPtr) event->message);
  795.             break;
  796.         case osEvt:
  797.             switch ((event->message >> 24) & 0x0FF) {
  798.                 case suspendResumeMessage:
  799.                     gInBackground = (event->message & resumeFlag) == 0;
  800.                     DoActivate(FrontWindow(), !gInBackground);
  801.                     break;
  802.             }
  803.             break;
  804.         }
  805. }
  806.  
  807. void DoActivate(WindowPtr window, Boolean becomingActive)
  808. {
  809. #pragma unused (window)
  810. #pragma unused (becomingActive)
  811.     //Could start and stop animation here
  812. }
  813.  
  814.  
  815. void DoUpdate(WindowPtr window)
  816. {
  817.     Rect geRect;
  818.     GEWorldPtr geWorld;
  819.  
  820.     if (window == gAnimWindow)
  821.     {
  822.         SetPort( (GrafPtr) window );
  823.         //Protect GEWorld rect before updating window, since we will draw it
  824.         geWorld = (GEWorldPtr) GetWRefCon(gAnimWindow);
  825.         geRect = geWorld->animationRect;
  826.         RectOffset(&geRect, geWorld->worldFocus.h, geWorld->worldFocus.v);
  827.         ValidRect(&geRect);
  828.         
  829.         BeginUpdate(window);
  830.             FillRgn(((GrafPtr) window)->visRgn, (ConstPatternParam) &qd.gray);
  831.         EndUpdate(window);
  832.         
  833.         DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  834.     }
  835. }
  836.  
  837. void AdjustMenus( void )
  838. {
  839.     WindowPtr    window;
  840.     MenuHandle    menu;
  841.     
  842.     window = FrontWindow();
  843.     
  844.     menu = GetMHandle(mFile);
  845.     EnableItem(menu, iQuit);
  846.  
  847.     menu = GetMHandle(mEdit);
  848.     if (window = gAnimWindow) {
  849.         DisableItem(menu, iUndo);
  850.         DisableItem(menu, iCut);
  851.         DisableItem(menu, iCopy);
  852.         DisableItem(menu, iClear);
  853.         DisableItem(menu, iPaste);
  854.     }
  855.     else {
  856.         EnableItem(menu, iUndo);
  857.         EnableItem(menu, iCut);
  858.         EnableItem(menu, iCopy);
  859.         EnableItem(menu, iClear);
  860.         EnableItem(menu, iPaste);
  861.     }
  862.     menu = GetMHandle(mSpecial);
  863.     //Set up special items!
  864.     EnableItem(menu, iSetParams);
  865.     EnableItem(menu, iMeter);
  866.     CheckItem(menu, iMeter, gMeterShown);
  867.     EnableItem(menu, iTiming);
  868. }
  869.  
  870. void DoMenuCommand(long menuResult)
  871. {
  872.     short        menuID;
  873.     short        menuItem;
  874.     Str255        daName;
  875.     short        daRefNum;
  876.  
  877.     menuID = HiWord(menuResult);
  878.     menuItem = LoWord(menuResult);
  879.     switch ( menuID ) {
  880.         case mApple:
  881.             switch ( menuItem ) {
  882.                 case iAbout:
  883.                     DoAboutBox();
  884.                     break;
  885.                 default:            /* all other items in this menu are DAs */
  886.                     GetItem(GetMHandle(mApple), menuItem, daName);
  887.                     daRefNum = OpenDeskAcc(daName);
  888.                     break;
  889.             }
  890.             break;
  891.         case mFile:
  892.             if (menuItem == iQuit)
  893.                 gFinished = true;
  894.             break;
  895.         case mEdit:
  896.             (void) SystemEdit(menuItem-1);
  897.             break;
  898.         case mSpecial:
  899.             //Add special items
  900.             switch ( menuItem ) {
  901.                 case iSetParams:
  902.                     DoSetParams();
  903.                     break;
  904.                 case iMeter:
  905.                     gMeterShown = !gMeterShown;
  906.                     ShowElement((GEWorldPtr) GetWRefCon(gAnimWindow), meterBkgID, gMeterShown);
  907.                     ShowElement((GEWorldPtr) GetWRefCon(gAnimWindow), meterIndID, gMeterShown);
  908.                     break;
  909.                 case iTiming:
  910.                     DoTimingLoop();
  911.                     break;
  912.                 case iSingleFrame:
  913.                     gSingleFrame = !gSingleFrame;
  914.                     break;
  915.             }
  916.             break;
  917.     }
  918.     HiliteMenu(0);
  919. }
  920.  
  921. //Utility routines
  922.  
  923.  
  924. void AdjustCursor( void )
  925. {
  926.     WindowPtr    window;
  927.     
  928.     window = FrontWindow();
  929.     
  930.     if ( (window == gAnimWindow) && (!gInBackground) ) {
  931.         SetCursor(&qd.arrow);
  932.     }
  933. }
  934.  
  935.